#include <GlobalData.h>
#include "EVector3.h"


template <typename TYPE>
Vector3<TYPE>::Vector3()
{
	// empty
}

template <typename TYPE>
Vector3<TYPE>::Vector3(TYPE x, TYPE y, TYPE z) :
	x(x),
	y(y),
	z(z)
{
	//
}

template <typename TYPE>
TYPE Vector3<TYPE>::length()
{
	return sqrt(x*x + y*y + z*z);
}

template <typename TYPE>
Vector3<TYPE>& Vector3<TYPE>::normalize()
{
	TYPE length = sqrt(x*x + y*y + z*z);
	x /= length;
	y /= length;
	z /= length;
	return *this;
}

template <typename TYPE>
Vector3<TYPE> Vector3<TYPE>::cross(const Vector3& other)
{
	Vector3 ret;
	ret.x = this->y * other.z - other.y * this->z;
	ret.y = this->z * other.x - other.z * this->x;
	ret.z = this->x * other.y - other.x * this->y;
	return ret;
}

template <typename TYPE>
TYPE Vector3<TYPE>::dot(const Vector3& other)
{
	return this->x * other.x + this->y * other.y + this->z * other.z;
}

template <typename TYPE>
Vector3<TYPE> Vector3<TYPE>::operator-()
{
	Vector3<TYPE> ret;
	ret.x = -this->x;
	ret.y = -this->y;
	ret.z = -this->z;
	return ret;
}

template <typename TYPE>
Vector3<TYPE> Vector3<TYPE>::operator*(float mul)
{
	Vector3<TYPE> ret;
	ret.x = this->x * mul;
	ret.y = this->y * mul;
	ret.z = this->z * mul;
	return ret;
}

template <typename TYPE>
Vector3<TYPE> Vector3<TYPE>::operator/(float div)
{
	Vector3<TYPE> ret;
	ret.x = this->x / div;
	ret.y = this->y / div;
	ret.z = this->z / div;
	return ret;
}

template <typename TYPE>
Vector2<TYPE> Vector3<TYPE>::xy()
{
	return Vector2<TYPE>(this->x, this->y);
}

template <typename TYPE>
Vector2<TYPE> Vector3<TYPE>::xz()
{
	return Vector2<TYPE>(this->x, this->z);
}

template <typename TYPE>
Vector2<TYPE> Vector3<TYPE>::yz()
{
	return Vector2<TYPE>(this->y, this->z);
}

template <typename TYPE>
Vector3<TYPE> Vector3<TYPE>::getUnitX()
{
	return Vector3<TYPE>(1.0, 1.0, 1.0);
}

template <typename TYPE>
Vector3<TYPE> Vector3<TYPE>::getUnitY()
{
	return Vector3<TYPE>(1.0, 1.0, 1.0);
}

template <typename TYPE>
Vector3<TYPE> Vector3<TYPE>::getUnitZ()
{
	return Vector3<TYPE>(1.0, 1.0, 1.0);
}

template <typename TYPE>
Vector3<TYPE> operator+(const Vector3<TYPE>& a, const Vector3<TYPE>& b)
{
    Vector3<TYPE> ret;
    ret.x = a.x + b.x;
    ret.y = a.y + b.y;
    ret.z = a.z + b.z;
    return ret;
}

template <typename TYPE>
Vector3<TYPE> operator-(const Vector3<TYPE>& a, const Vector3<TYPE>& b)
{
    Vector3<TYPE> ret;
    ret.x = a.x - b.x;
    ret.y = a.y - b.y;
    ret.z = a.z - b.z;
    return ret;
}

INSTANTIATE_VECTOR_TEMPLATE(Vector3)

template Vector3<float> 	operator+(const Vector3<float>&  a, const Vector3<float>&  b);
template Vector3<double> 	operator+(const Vector3<double>& a, const Vector3<double>& b);
template Vector3<int> 		operator+(const Vector3<int>&    a, const Vector3<int>&    b);
template Vector3<float> 	operator-(const Vector3<float>&  a, const Vector3<float>&  b);
template Vector3<double> 	operator-(const Vector3<double>& a, const Vector3<double>& b);
template Vector3<int> 		operator-(const Vector3<int>&    a, const Vector3<int>&    b);


